#include <iostream>
#include <process.h>

#include <remotefunction.h>

struct basic
{
	int m[5];
};

struct data
{
	int a;
	char d;
	basic x;
};

class complex
{
public:
	std::string str;
	data y;
};

NAMESPACE_BEGIN(kog);

template<> kog::serial& kog::serial::append<complex>(const complex& x)
{
	return append(x.str).append(x.y);
}

template<> kog::unserial& kog::unserial::getvalue<complex>(complex& x)
{
	return getvalue(x.str).getvalue(x.y);
}

NAMESPACE_END(kog);

complex combine(std::string s, data d)
{
	complex c;
	c.str = s;
	c.y = d;
	return c;
}

kog::remote_function* g_rfServer = NULL;
kog::remote_function* g_rfClient = NULL;
std::string g_pipename = "\\\\.\\pipe\\testmt";
void server(void*)
{
	kog::pipe pserver(g_pipename, kog::pipe::server_port);
	pserver.waitclient();

	kog::remote_function rfServer(pserver);
	g_rfServer = &rfServer; 
	g_rfServer->entry("combine", combine);
	g_rfServer->start_service();
}

void client(void*)
{
	kog::pipe pclient(g_pipename, kog::pipe::client_port);
	pclient.connectserver();
	kog::remote_function rfclient(pclient);

	g_rfClient = &rfclient; 
	g_rfClient->start_service();
}

int main(int argc, const char* argv[])
{
	kog::os::osobject hserver, hclient;
	hserver.create_thread(kog::unary2zero(std::ptr_fun(server), (void*)NULL));
	kog::os::osobject::sleep(100);
	hclient.create_thread(kog::unary2zero(std::ptr_fun(client), (void*)NULL));
	kog::os::osobject::sleep(100);
	

	std::string s = "abc";
	data d;
	d.a = 20;
	d.d = 'c';
	d.x.m[0] = 1;
	d.x.m[1] = 2;
	d.x.m[2] = 3;
	d.x.m[3] = 4;
	d.x.m[4] = 5;


	std::cout<<"input:"
		<<"\ns = "<<s
		<<"\nd.a = "<<d.a
		<<"\nd.d = "<<d.d
		<<"\nd.x.m[0] = "<<d.x.m[0]
		<<"\nd.x.m[1] = "<<d.x.m[1]
		<<"\nd.x.m[2] = "<<d.x.m[2]
		<<"\nd.x.m[3] = "<<d.x.m[3]
		<<"\nd.x.m[4] = "<<d.x.m[4]
		<<std::endl;
	complex ret = (*g_rfClient)["combine"].makecall<complex>(s, d);

	std::cout<<"output:"
		<<"\nret.str = "<<ret.str
		<<"\nret.y.a = "<<ret.y.a
		<<"\nret.y.d = "<<ret.y.d
		<<"\nret.y.x.m[0] = "<<ret.y.x.m[0]
		<<"\nret.y.x.m[1] = "<<ret.y.x.m[1]
		<<"\nret.y.x.m[2] = "<<ret.y.x.m[2]
		<<"\nret.y.x.m[3] = "<<ret.y.x.m[3]
		<<"\nret.y.x.m[4] = "<<ret.y.x.m[4]
		<<std::endl;
	g_rfServer->stop_service();

	return 0;
}